package com.bianguo.android.functiondemo.proxy;

import com.bianguo.android.functiondemo.utils.MLog;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Objects;

public class ProxyFactory {

    private static volatile ProxyFactory mFactory;

    private ProxyFactory() {
    }

    public static ProxyFactory getInstance() {
        ProxyFactory proxyFactory = mFactory;
        if (proxyFactory == null) {
            synchronized (ProxyFactory.class) {
                if (proxyFactory == null) {
                    proxyFactory = new ProxyFactory();
                    mFactory = proxyFactory;
                }
            }
        }
        return proxyFactory;
    }

    public Object getProxy(Object target) {
        Class<? extends Object> aClass = target.getClass();
        Object newProxyInstance = Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), (proxy, method, args) -> {
            Object invoke = method.invoke(target, args);
            return invoke;
        });
//        Object newProxyInstance = Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), new InvocationHandler() {
//            @Override
//            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
//                Object invoke = method.invoke(target, objects);
//                return invoke;
//            }
//        });
        return newProxyInstance;
    }

    @SuppressWarnings("unchecked")
    public <T> T getProxy(Class<T> cls, T target) {
        return (T) Proxy.newProxyInstance(cls.getClassLoader(), new Class<?>[] {cls}, (proxy, method, args) -> {
            Class<?> declaringClass = method.getDeclaringClass();
            if (declaringClass == Object.class) {
                return method.invoke(this, args);
            }
            MLog.mLog("" + cls.getName());
            Object returnValue = method.invoke(target, args);
            return returnValue;
        });
    }
}
